package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.constants.RedisConstants;
import com.tianji.learning.domain.po.PointsRecord;
import com.tianji.learning.domain.vo.PointsStatisticsVO;
import com.tianji.learning.enums.PointsRecordType;
import com.tianji.learning.mapper.PointsRecordMapper;
import com.tianji.learning.mq.msg.SignInMessage;
import com.tianji.learning.service.IPointsRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.xml.crypto.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 学习积分记录，每个月底清零 服务实现类
 * </p>
 *
 * @author liuchun
 * @since 2024-09-07
 */
@Service
public class PointsRecordServiceImpl extends ServiceImpl<PointsRecordMapper, PointsRecord> implements IPointsRecordService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 向积分表中插入积分数据
     * @param message
     * @param type
     */
    @Override
    public void addPointsRecord(SignInMessage message, PointsRecordType type) {
        //获取登录用户
        //todo userId 空指针
        Long userId = message.getUserId();
        //校验消息
        if (message.getUserId() == null || message.getPoints() == null){
            return;
        }
        int maxPoints = type.getMaxPoints();
        int realPoints = message.getPoints();
        //当前时间
        LocalDate now = LocalDate.now();
        if (maxPoints > 0) {
            LocalDateTime begin = DateUtils.getMonthBeginTime(now);
            LocalDateTime end = DateUtils.getMonthEndTime(now);
            //查询当前用户当天获得最大积分
            LambdaQueryWrapper<PointsRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.apply("sum (points) as totalPoints");
            wrapper.eq(PointsRecord::getUserId, message.getUserId());
            wrapper.eq(PointsRecord::getType, type);
            wrapper.between(PointsRecord::getCreateTime, begin, end);
            Map<String, Object> map = this.getMap(wrapper);
            int currentPoints = 0;
            if (map != null) {
                BigDecimal totalPoints = (BigDecimal) map.get("totalPoints");
                currentPoints = totalPoints.intValue();
            }
            if (currentPoints >= maxPoints) {
                return;
            }
            if (currentPoints + message.getPoints() > maxPoints) {
                realPoints = maxPoints - currentPoints;
            }
        }
            //保存积分
            PointsRecord pointsRecord = new PointsRecord();
            pointsRecord.setUserId(message.getUserId());
            pointsRecord.setType(type);
            pointsRecord.setPoints(realPoints);
            save(pointsRecord);

            //将积分累加到Redis
            String format = now.format(DateTimeFormatter.ofPattern("yyyyMM"));
            String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + format;
            redisTemplate.opsForZSet().incrementScore(key, userId.toString(), realPoints);
        }

    /**
     * 查询今日积分情况
     * @return
     */
    @Override
    public List<PointsStatisticsVO> getTodayPoints() {
        Long userId = UserContext.getUser();
        LocalDate now = LocalDate.now();
        LocalDateTime begin = DateUtils.getMonthBeginTime(now);
        LocalDateTime end = DateUtils.getMonthEndTime(now);
        QueryWrapper<PointsRecord> wrapper = new QueryWrapper<>();
        wrapper.select("type,sum(points) as points");
        wrapper.eq("user_id",userId);
        wrapper.between("create_time",begin,end);
        wrapper.groupBy("type");
        List<PointsRecord> list = list(wrapper);
        if (CollUtils.isEmpty(list)) {
           return CollUtils.emptyList();
       }
        List<PointsStatisticsVO> vos = new ArrayList<>();
        for (PointsRecord record : list) {
            PointsStatisticsVO vo = new PointsStatisticsVO();
            vo.setType(record.getType().getDesc());
            vo.setMaxPoints(record.getType().getMaxPoints());
            vo.setPoints(record.getPoints());
            vos.add(vo);
        }
       return vos;
    }
}
